package com.ericsson.common.pojo;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/**
 *
 * 自定义文件锁
 *
 * @author JiangTao
 *
 */
public abstract class MyFileLock {

	/**
	 * 文件随机访问器
	 */
	protected RandomAccessFile randomAccessFile;

	/**
	 * 文件通道
	 */
	protected FileChannel fileChannel;

	/**
	 * 文件锁
	 */
	protected FileLock fileLock;

	/**
	 * 要锁定的文件
	 */
	protected File file;

	/**
	 * 阻塞
	 */
	protected boolean block;

	public MyFileLock() {

	}

	/**
	 * 创建指定文件锁对象
	 *
	 * @param file
	 */
	public MyFileLock(File file) {
		this.file = file;
	}

	/**
	 * 创建指定文件锁对象
	 *
	 * @param block
	 */
	public MyFileLock(boolean block) {
		this.block = block;
	}

	/**
	 * 创建指定文件锁对象
	 *
	 * @param file
	 */
	public MyFileLock(File file, boolean block) {

		this.file = file;

		this.block = block;
	}

	/**
	 * 获取锁
	 *
	 * @return
	 */
	public boolean obtain() {

		try {

			if (null == this.fileChannel) {

				this.randomAccessFile = new RandomAccessFile(this.file, "rw");

				this.fileChannel = this.randomAccessFile.getChannel();

				this.fileLock = this.fileChannel.tryLock();

				return this.fileLock != null ? true : false;

			} else if (null != this.fileChannel && this.fileChannel.isOpen()) {

				if (null == this.fileLock) {

					this.fileLock = this.fileChannel.tryLock();

					return this.fileLock != null ? true : false;

				} else {

					String fileLockChannel = this.fileLock.channel().toString();

					String channelExists = this.fileChannel.toString();

					if (channelExists.equals(fileLockChannel)) {

						return true;

					} else {

						return false;
					}
				}

			} else if (null != this.fileChannel && !this.fileChannel.isOpen()) {

				this.randomAccessFile = new RandomAccessFile(this.file, "rw");

				this.fileChannel = this.randomAccessFile.getChannel();

				if (null != this.fileLock && this.fileLock.isValid()) {

					this.fileLock.release();

				}

				this.fileLock = this.fileChannel.tryLock();

				return this.fileLock != null ? true : false;

			} else {

				return false;
			}

		} catch (Exception ex) {

			return false;

		}
	}

	/**
	 * 释放锁
	 *
	 * @return
	 */
	public boolean release() {

		try {

			if(null != this.fileLock) {

				this.fileLock.release();

				this.fileLock = null;
			}

			if (null != this.fileChannel && this.fileChannel.isOpen()) {

				this.fileChannel.close();

				this.fileChannel = null;
			}

			if (null != this.randomAccessFile) {

				this.randomAccessFile.close();

				this.randomAccessFile = null;
			}

			return true;

		} catch (Exception ex) {

			return false;
		}
	}

	/**
	 *
	 */
	public void run() {

		try {

			boolean isObtain = this.obtain();

			if (this.block) {

				while (!isObtain) {

					isObtain = this.obtain();
				}
			}

			doFile();

		} catch (Exception ex) {

			ex.printStackTrace();

		} finally {

			this.release();
		}
	}

	/**
	 * 执行方法
	 */
	protected abstract void doFile() throws Exception;

	public RandomAccessFile getRandomAccessFile() {
		return randomAccessFile;
	}

	public FileChannel getFileChannel() {
		return fileChannel;
	}

	public FileLock getFileLock() {
		return fileLock;
	}

	public File getFile() {
		return file;
	}

	public void setFile(File file) {
		this.file = file;
	}

	public boolean isBlock() {
		return block;
	}

	public void setBlock(boolean block) {
		this.block = block;
	}
}
